package com.dtp.common.util;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.Assert;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Stream数据流处理工具类
 *
 * @author yanhom
 * @since 1.0.0
 *
 * @remark muse
 **/
public final class StreamUtil {

    private StreamUtil() {}

    /** 获取data集合中元素的某个属性，并组成集合，具体是哪个属性，在mapping函数中实现 */
    public static <I, T> List<I> fetchProperty(Collection<T> data, Function<T, I> mapping) {
        Assert.notNull(mapping, "mapping function must not be null");
        if (CollectionUtils.isEmpty(data)) return Collections.emptyList();

        return data.stream().map(mapping).collect(Collectors.toList());
    }

    /** 转换为映射（key从列表数据coll中通过Function函数获取）*/
    public static <P, O> Map<O, P> toMap(Collection<P> coll, Function<P, O> key) {
        Assert.notNull(key, "key function must not be null");
        if (CollectionUtils.isEmpty(coll)) return Collections.emptyMap();

        return coll.stream().collect(Collectors.toMap(key, Function.identity(), (v1, v2) -> v2));
    }

    /** 转换为映射（key和value都从列表数据coll中通过Function函数获取）*/
    public static <O, D, P> Map<O, P> toMap(Collection<D> list,
                                            Function<D, O> key,
                                            Function<D, P> value) {
        Assert.notNull(key, "Key function must not be null");
        Assert.notNull(value, "Value function must not be null");
        if (CollectionUtils.isEmpty(list)) return Collections.emptyMap();

        return list.stream().collect(Collectors.toMap(key, value, (v1, v2) -> v2));
    }

    /** 将list转换为列表映射，其中列表包含ids中的id */
    public static <I, D> Map<I, List<D>> toListMap(Collection<I> ids,
                                                   Collection<D> list,
                                                   Function<D, I> key) {
        Assert.notNull(key, "mapping function must not be null");
        if (CollectionUtils.isEmpty(ids) || CollectionUtils.isEmpty(list)) return Collections.emptyMap();

        Map<I, List<D>> resultMap = list.stream().collect(Collectors.groupingBy(key));
        ids.forEach(id -> resultMap.putIfAbsent(id, Collections.emptyList()));
        return resultMap;
    }

}
